using System;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;
using needle.UI.Controls.Flat.Utilities;
using needle.UI.Controls.Flat.Utilities.Win32;
using needle.UI.Controls.Flat.Windows.Forms;
using needle.UI.Controls.Flat.Windows.Forms.Collections;

namespace needle.UI.Controls.Flat.Windows.Docking
{
    [ToolboxItem(false)]
    public class WindowContentTabbed : WindowContent, IHotZoneSource, IMessageFilter
    {
        protected static int mplainBorder = 3;
        protected static int mhotAreaInflate = -3;

        protected int mdragPageIndex;
        protected Content mactiveContent;
        protected RedockerContent mredocker;
        protected needle.UI.Controls.Flat.Windows.Forms.TabControl mtabControl;

		#region Constructors
		
		public WindowContentTabbed(DockingManager manager) : base(manager)
        {
            mredocker = null;
            mactiveContent = null;
            
            mtabControl = new needle.UI.Controls.Flat.Windows.Forms.TabControl();
			mtabControl.Style = manager.Style;

            mtabControl.Dock = DockStyle.Fill;

            mtabControl.HideTabsMode = needle.UI.Controls.Flat.Windows.Forms.TabControl.HideTabsModes.HideUsingLogic;
            
            mtabControl.GotFocus += new EventHandler(OnTabControlGotFocus);
            mtabControl.LostFocus += new EventHandler(OnTabControlLostFocus);
            mtabControl.PageGotFocus += new EventHandler(OnTabControlGotFocus);
            mtabControl.PageLostFocus += new EventHandler(OnTabControlLostFocus);
            mtabControl.SelectionChanged += new EventHandler(OnSelectionChanged);
            mtabControl.PageDragStart += new MouseEventHandler(OnPageDragStart);
            mtabControl.PageDragMove += new MouseEventHandler(OnPageDragMove);
            mtabControl.PageDragEnd += new MouseEventHandler(OnPageDragEnd);
            mtabControl.PageDragQuit += new MouseEventHandler(OnPageDragQuit);
            mtabControl.DoubleClickTab += new needle.UI.Controls.Flat.Windows.Forms.TabControl.DoubleClickTabEventHandler(OnDoubleClickTab);
			mtabControl.Font = manager.TabControlFont;
            
			if (mtabControl.Style == null)
			{
				mtabControl.BackColor = manager.BackColor;
				mtabControl.ForeColor = manager.InactiveTextColor;
			}

			manager.OnTabControlCreated(mtabControl);

            Controls.Add(mtabControl);

			Application.AddMessageFilter(this);
        }

		#endregion

		#region Overrides
        
		public override void BringContentToFront(Content c)
		{
            foreach(needle.UI.Controls.Flat.Windows.Forms.TabPage page in mtabControl.TabPages)
                if (page.Tag == c)
                {
                    mtabControl.SelectedTab = page;
                    break;
                }
		}

        public override void PropogateNameValue(PropogateName name, object value)
        {
            base.PropogateNameValue(name, value);
        
            switch(name)
            {
                case PropogateName.BackColor:
                    Color newColor = (Color)value;
            
                    mtabControl.BackColor = newColor;
                    this.BackColor = newColor;
                    
                    Invalidate();
                    break;
                case PropogateName.InactiveTextColor:
                    mtabControl.ForeColor = (Color)value;
                    break;
                case PropogateName.PlainTabBorder:
                    mtabControl.InsetBorderPagesOnly = !(bool)value;
                    break;
				case PropogateName.TabControlFont:
					mtabControl.Font = (Font)value;
					break;
            }
        }

        protected override void OnContentsClearing(object sender, EventArgs e)
        {
            mtabControl.TabPages.Clear();

            base.OnContentsClearing(null, EventArgs.Empty);

            if (!this.AutoDispose)
            {
                NotifyFullTitleText("");
            }
        }

        protected override void OnContentInserted(object sender, needle.UI.Controls.Flat.Windows.Forms.Collections.CollectionChangeEventArgs e)
        {
            base.OnContentInserted(sender, e);

            Content content = sender as Content;

            needle.UI.Controls.Flat.Windows.Forms.TabPage newPage = new needle.UI.Controls.Flat.Windows.Forms.TabPage();

            newPage.Title = content.Title;
            newPage.ImageList = content.ImageList;
            newPage.ImageIndex = content.ImageIndex;
            newPage.Icon = content.Icon;
			newPage.Control = content.Control;
			newPage.Tag = content;
			
            mtabControl.TabPages.Insert(e.Index, newPage);
        }

        protected override void OnContentRemoving(object sender, needle.UI.Controls.Flat.Windows.Forms.Collections.CollectionChangeEventArgs e)
        {
            base.OnContentRemoving(sender, e);

            Content c = sender as Content;

            foreach(needle.UI.Controls.Flat.Windows.Forms.TabPage page in mtabControl.TabPages)
                if (page.Tag == c)
                {
                    mtabControl.TabPages.Remove(page);
                    break;
                }
        }

        public override void WindowDetailGotFocus(WindowDetail wd)
        {
            mtabControl.Focus();
        }

		protected override void OnContentChanged(object obj, Content.PropChangeEventArgs e)
		{
			foreach(needle.UI.Controls.Flat.Windows.Forms.TabPage page in mtabControl.TabPages)
			{
				if (page.Tag == obj)
				{
					switch(e.PropertyName)
					{
						case "Control":
							page.Control = ((Content)obj).Control;
							break;
						case "Title":
							page.Title = ((Content)obj).Title;
							break;
						case "FullTitle":
							if (mtabControl.SelectedTab == page)
							{
								NotifyFullTitleText(((Content)obj).FullTitle);
							}								
							break;
						case "ImageList":
							page.ImageList = ((Content)obj).ImageList;
							break;
						case "ImageIndex":
							page.ImageIndex = ((Content)obj).ImageIndex;
							break;
						case "Icon":
							page.Icon = ((Content)obj).Icon;
							break;
						case "CaptionBar":
							if (mtabControl.SelectedTab == page)
							{
								Content target = page.Tag as Content;
								NotifyShowCaptionBar(target.CaptionBar);                                
							}
							break;
						case "CloseButton":
							if (mtabControl.SelectedTab == page)
							{
								Content target = page.Tag as Content;
                        
								NotifyCloseButton(target.CloseButton);   
							}
							break;
						case "HideButton":
							if (mtabControl.SelectedTab == page)
							{
								Content target = page.Tag as Content;
								NotifyHideButton(target.HideButton);   
							}
							break;
					}

					break;
				}
			}
		}

		protected override void OnResize(EventArgs e)
		{
			foreach(Content c in mcontents)
			{
				switch(mstate)
				{
					case State.DockLeft:
					case State.DockRight:
						if (this.Dock != DockStyle.Fill)
						{
							c.DisplaySize = new Size(this.ClientSize.Width, c.DisplaySize.Height);
						}
						break;
					case State.DockTop:
					case State.DockBottom:
						if (this.Dock != DockStyle.Fill)
						{
							c.DisplaySize = new Size(c.DisplaySize.Width, this.ClientSize.Height);
						}
						break;
					case State.Floating:
					{
						Form f = this.FindForm();

						if (f == null)
							c.DisplaySize = this.ClientSize;
						else
							c.DisplaySize = f.Size;
					}
						break;
				}
			}

			base.OnResize(e);
		}
        
		public override Restore RecordRestore(object child) 
		{
			Content c = child as Content;

			StringCollection next = new StringCollection();
			StringCollection previous = new StringCollection();

			bool before = true;

			foreach(Content content in mcontents)
			{
				if (content == c)
					before = false;
				else
				{
					if (before)
						previous.Add(content.Title);
					else
						next.Add(content.Title);
				}
			}

			bool selected = false;

			if (mtabControl.SelectedIndex != -1)
			{
				Content selectedContent = mtabControl.SelectedTab.Tag as Content;

				selected = (selectedContent == c);
			}

			Restore thisRestore = new RestoreWindowContent(null, c, next, previous, selected);

			if (mparentZone != null)
			{
				thisRestore = mparentZone.RecordRestore(this, child, thisRestore);
			}

			return thisRestore;
		}

		#endregion

		#region Virtuals

        protected void OnSelectionChanged(object sender, EventArgs e)
        {
            if (mtabControl.TabPages.Count == 0)
            {
                NotifyFullTitleText("");
            }
            else
            {
                if (mtabControl.SelectedIndex != -1)
                {
                    Content selectedContent = mtabControl.SelectedTab.Tag as Content;
                    
                    NotifyAutoHideImage(selectedContent.AutoHidden);
                    NotifyCloseButton(selectedContent.CloseButton);
                    NotifyHideButton(selectedContent.HideButton);
                    NotifyFullTitleText(selectedContent.FullTitle);
                    NotifyShowCaptionBar(selectedContent.CaptionBar);
                }
            }
        }

        protected void OnTabControlGotFocus(object sender, EventArgs e)
        {
            NotifyContentGotFocus();
        }

        protected void OnTabControlLostFocus(object sender, EventArgs e)
        {
            NotifyContentLostFocus();
        }

		protected void OnDoubleClickTab(object sender, needle.UI.Controls.Flat.Windows.Forms.TabControl.TabPageEventArgs e)
		{
			Content c = (Content)((needle.UI.Controls.Flat.Windows.Forms.TabPage)e.Page).Tag;

			c.RecordRestore();

			c.Docked = (c.Docked == false);

			mmanager.HideContent(c, false, true);
			mmanager.ShowContent(c);
		}
		
        protected void OnPageDragStart(object sender, MouseEventArgs e)
        {
            if (this.RedockAllowed)
            {
                needle.UI.Controls.Flat.Windows.Forms.TabPage page = mtabControl.SelectedTab;

                Content c = page.Tag as Content;

                mdragPageIndex = mtabControl.TabPages.IndexOf(page);

                mtabControl.TabPages.Remove(page);

                this.Refresh();

                mredocker = new RedockerContent(mtabControl, c, this, new Point(e.X, e.Y));
            }
        }

        protected void OnPageDragMove(object sender, MouseEventArgs e)
        {
            if (mredocker != null)
                mredocker.OnMouseMove(e);
        }

        protected void OnPageDragEnd(object sender, MouseEventArgs e)
        {
            if (mredocker != null)
            {
                bool moved = mredocker.OnMouseUp(e);

                if (!moved)
                {
                    RestoreDraggingPage();
                }

                mredocker = null;
            }
        }

        protected void OnPageDragQuit(object sender, MouseEventArgs e)
        {
            if (mredocker != null)
            {
				mredocker.QuitTrackingMode(e);

                RestoreDraggingPage();

                mredocker = null;
            }
        }

		protected void RestoreDraggingPage()
		{
			needle.UI.Controls.Flat.Windows.Forms.TabPage newPage = new needle.UI.Controls.Flat.Windows.Forms.TabPage();

			Content content = mredocker.Content;

			newPage.Title = content.Title;

			newPage.ImageList = content.ImageList;
			newPage.ImageIndex = content.ImageIndex;
			newPage.Icon = content.Icon;
			newPage.Control = content.Control;
			newPage.Tag = content;
			newPage.Selected = true;
		
			mtabControl.TabPages.Insert(mdragPageIndex, newPage);

			NotifyFullTitleText(content.FullTitle);
		}

		#endregion

		#region Methods
		
		[UseApiElements("WM_KEYDOWN, VK_ESCAPE")]
		public bool PreFilterMessage(ref Message m)
		{
			if (m.Msg == (int)Msgs.WM_KEYDOWN)
			{
				if ((int)m.WParam == (int)VirtualKeys.VK_ESCAPE)
				{                   
					if (mredocker != null)
					{
						mredocker.QuitTrackingMode(null);

						RestoreDraggingPage();
                        
						mredocker = null;
                        
						return true;
					}
				}
			}
            
			return false;
		}

		public void HideCurrentContent()
		{
			needle.UI.Controls.Flat.Windows.Forms.TabPage tp = mtabControl.SelectedTab;
            
			int count = mtabControl.TabPages.Count;

			int index = mtabControl.SelectedIndex;

			if (count > 1)
			{
				int newSelect = index + 1;

				if (newSelect == count)
					newSelect = 0;

				mtabControl.SelectedIndex = newSelect;
			}
			else
			{
				this.Hide();

				mmanager.Container.Focus();
			}

			if (tp != null)
			{
				Content c = tp.Tag as Content;

				mmanager.HideContent(c);

				if (c.CloseOnHide)
				{
					mmanager.Contents.Remove(c);

					if (c.Control != null)
						c.Control.Dispose();
				}
			}
		}

		public void AddHotZones(Redocker redock, HotZoneCollection collection)
		{
			RedockerContent redocker = redock as RedockerContent;

			bool itself = false;
			bool nullZone = false;

			if ((redocker.WindowContent != null) && (redocker.WindowContent == this))
				itself = true;

			if (itself && !mcontents.Contains(redocker.Content))
				nullZone = true;

			Rectangle newSize = this.RectangleToScreen(this.ClientRectangle);
			Rectangle hotArea = mtabControl.RectangleToScreen(mtabControl.ClientRectangle);;

			foreach(WindowDetail wd in mwindowDetails)
			{
				WindowDetailCaption wdc = wd as WindowDetailCaption;

				if (wdc != null)
				{
					hotArea = wdc.RectangleToScreen(wdc.ClientRectangle);
					hotArea.Inflate(mhotAreaInflate, mhotAreaInflate);
					break;
				}
			}

			if (nullZone)
				collection.Add(new HotZoneNull(hotArea));
			else
				collection.Add(new HotZoneTabbed(hotArea, newSize, this, itself));				
		}

		#endregion

		#region Properties

		public Content CurrentContent
		{
			get
			{
				needle.UI.Controls.Flat.Windows.Forms.TabPage tp = mtabControl.SelectedTab;
                
				if (tp != null)
					return (Content)tp.Tag;
				else
					return null;
			}
		}

		public needle.UI.Controls.Flat.Windows.Forms.TabControl TabControl
		{
			get { return mtabControl; } 
		}

		#endregion

    }
}